// SSLClient.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


#ifdef WIN32
#include <Winsock2.h>         // For socket(), connect(), send(), and recv()  
#else  
#endif

#include <openssl/rsa.h>       
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>


#define DEFAULT_SERVER_IP_ADDR "127.0.0.1"
#define DEFAULT_SERVER_PORT 9090


int CreateTCPClientSock(unsigned int uiIP, int nPort)
{
	int iRet  = -1;
	int iFD = -1;
	do
	{
#ifdef WIN32
		static int nFirstTime = 1;
		if (1 == nFirstTime) 
		{
			WORD wVersionRequested;
			WSADATA wsaData;

			wVersionRequested = MAKEWORD(2, 0); // Request WinSock v2.0
			if (WSAStartup(wVersionRequested, &wsaData) != 0)
			{  // Load WinSock DLL
				return iFD;
			}
			nFirstTime = 0;
		}
#endif
		iFD = socket (AF_INET, SOCK_STREAM, 0); 
		if (-1 == iFD)
		{
			break;
		}
		struct sockaddr_in sa_serv;  
		memset (&sa_serv, '\0', sizeof(sa_serv));
		sa_serv.sin_family      = AF_INET;
		sa_serv.sin_addr.s_addr = uiIP;
		sa_serv.sin_port        = htons (nPort);      
		iRet = connect(iFD, (struct sockaddr*) &sa_serv,sizeof(sa_serv));  
		if(-1 == iRet)
		{
			break;
		}		
	} while(0);
	if (iRet == -1)
	{
		char acMsgBuf[128]="";
		strerror_s( acMsgBuf, sizeof(acMsgBuf), errno);
		printf("TCP Socket can not be opened.Reason %s \n", acMsgBuf);
		return iFD = -1;
	}	
	return iFD;

}

void CloseSocket(int iFD) 
{
#ifdef WIN32
	::closesocket(iFD);
#else
	::close(sockDesc);
#endif  
}

void PrintHelp()
{
	printf("Format for inputs parameters:\n");
	printf("<UserID> <UserPassword> <Server IP > <Serverport> \n");
}
int main(int argc, char* argv[])
{
	int iRet = EXIT_FAILURE;
	if ((argc>=2) &&
		( 0 == _stricmp(argv[1],"Help"))
		)
	{
		PrintHelp();
		return EXIT_SUCCESS;
	}
	int nServerPort = DEFAULT_SERVER_PORT;
	const char* pcServerIP = DEFAULT_SERVER_IP_ADDR;
	const char* pcUserID = "TEST";
	const char* pcUserPass = "TESTPASS";
	if (argc>=2)
	{
		pcUserID = argv[1];
	}
	if (argc>=3)
	{
		pcUserPass = argv[2];
	}
	if (argc>=4)
	{
		pcServerIP = (argv[3]);
	}
	if (argc>=5)
	{
		nServerPort = atoi(argv[4]);
	}
	
	unsigned int uiServerIP = 0;
	uiServerIP = inet_addr (pcServerIP);

	printf("Starting application %s with server IP %s and Server port %d\n",argv[0], pcServerIP, nServerPort );
	SSL*  psSsl = NULL;
	SSL_CTX* psCtx = NULL;
	int iFD = -1;
	do
	{ 
		SSLeay_add_ssl_algorithms();		
		SSL_load_error_strings();
		const SSL_METHOD* psMeth = SSLv2_client_method();
		psCtx = SSL_CTX_new(psMeth);		
		if (NULL == psCtx) 
		{
			ERR_print_errors_fp(stderr);
			break;
		}
		psCtx = SSL_CTX_new (psMeth); 
		if(NULL ==psCtx )
		{
			break;
		}
		psSsl = SSL_new (psCtx);   
		if (NULL == psSsl)
		{
			break;
		}			

		iRet = CreateTCPClientSock(uiServerIP,nServerPort);
		if (-1 == iRet)
		{
			break;
		}
		iFD = iRet;		
		SSL_set_fd (psSsl, iFD);
		iRet = SSL_connect (psSsl); 
		if (-1 == iRet)
		{
			break;
		}
		printf ("SSL connection using %s\n", SSL_get_cipher (psSsl));

		/*do authentication here*/
		char acMsg[1400];
		sprintf_s(acMsg,"UserID:%s,Password:%s", pcUserID, pcUserPass);
		iRet = SSL_write (psSsl, acMsg, strlen(acMsg));  
		if (-1 == iRet)
		{
			break;
		}
		memset(acMsg,0,sizeof(acMsg));
		iRet = SSL_read (psSsl, acMsg, sizeof(acMsg));                  
		if (-1 == iRet)
		{
			break;
		}		
		printf ("Got %d chars:'%s'\n", iRet, acMsg);  
		SSL_shutdown (psSsl); 
		iRet = EXIT_SUCCESS;
	} while(0);
	if (-1 != iFD)
	{
		CloseSocket(iFD);
	}

	if (NULL!=psSsl)
	{
		SSL_free (psSsl);
	}
	if(NULL!=psCtx)
	{
		SSL_CTX_free (psCtx);
	}

	return iRet ;
}

